from typing import Optional, List

from extract.extractor import Extractor
from src.config.parameter import Parameter
from src.downloader.download import Downloader
from src.handle.acquirer import Acquirer
from src.tools.retry import PrivateRetry


def generate_live_params(rid: bool, ids: List[list]) -> List[dict]:
    if not ids:
        print("提取 web_rid 或者 room_id 失败！")
        return []
    if rid:
        return [{"web_rid": id_} for id_ in ids]
    else:
        return [{"room_id": id_[0], "sec_user_id": id_[1]} for id_ in ids]


def choice_live_quality(
        flv_items: dict,
        m3u8_items: dict,
        choice_) -> Optional[tuple]:
    try:
        if u := flv_items.get(choice_):
            return u, m3u8_items.get(choice_)
        if not 0 <= (i := int(choice_) - 1) < len(flv_items):
            raise ValueError
    except ValueError:
        return None
    return list(flv_items.values())[i], list(m3u8_items.values())[i]


class Live(Acquirer):
    live_api = "https://live.douyin.com/webcast/room/web/enter/"
    live_api_share = "https://webcast.amemv.com/webcast/room/reflow/info/"

    def __init__(
            self,
            params: Parameter,
            web_rid=None,
            room_id=None,
            sec_user_id=None):
        super().__init__(params)
        self.parameter = params
        self.extractor = Extractor(params)
        self.PC_headers["Referer"] = "https://live.douyin.com/"
        self.web_rid = web_rid
        self.room_id = room_id
        self.sec_user_id = sec_user_id
        self.downloader = Downloader(params)

    def run(self) -> dict:
        if self.web_rid:
            return self.with_web_rid()
        elif self.room_id:
            return self.with_room_id()
        else:
            return {}

    def live_interactive(self, params, choice=1):
        live_data = [Live(self.parameter, **i).run() for i in params]
        if not [i for i in live_data if i]:
            print("获取直播数据失败")
            return []
        live_data = self.extractor.run(live_data, "live")
        download_tasks = self.show_live_info(live_data, choice)
        return self.downloader.run_live(download_tasks)


    def show_live_info(self, data: List[dict],choice=1) -> List[tuple]:
        download_tasks = []
        for item in data:
            print("直播标题:", item["title"])
            print("主播昵称:", item["nickname"])
            print("在线观众:", item["user_count_str"])
            print("观看次数:", item["total_user_str"])
            if item["status"]==4:
                print("当前直播已结束！")
                continue
            self.show_live_stream_url(item, download_tasks, choice)
        return [i for i in download_tasks if isinstance(i, tuple)]

    def show_live_stream_url(self, item: dict, tasks: list, choice=1):
        print("FLV 推流地址: ")
        for i, (k, v) in enumerate(item["flv_pull_url"].items(), start=1):
            print(i, k, v)
        print("M3U8 推流地址: ")
        for i, (k, v) in enumerate(item["hls_pull_url_map"].items(), start=1):
            print(i, k, v)
        if self.parameter.download:
            tasks.append(
                (item,
                 *
                 u) if (
                    u := choice_live_quality(
                        item["flv_pull_url"],
                        item["hls_pull_url_map"], choice)) else u)

    def with_web_rid(self) -> dict:
        params = {
            "aid": "6383",
            "app_name": "douyin_web",
            "device_platform": "web",
            "language": "zh-CN",
            "enter_from": "web_live",
            "cookie_enabled": "true",
            "web_rid": self.web_rid,
        }
        api = self.live_api
        self.deal_url_params(params)
        return self.get_live_data(api, params)

    def with_room_id(self) -> dict:
        params = {
            "type_id": "0",
            "live_id": "1",
            "room_id": self.room_id,
            "sec_user_id": self.sec_user_id,
            "version_code": "99.99.99",
            "app_id": "1128",
        }
        api = self.live_api_share
        headers = self.black_headers
        self.deal_url_params(params, 4)
        return self.get_live_data(api, params, headers)

    def stop_live_interactive(self, processIds: dict):
        return [self.parameter.ffmpeg.stop_process(i) for i in processIds]

    @PrivateRetry.retry
    def get_live_data(
            self,
            api: str,
            params: dict,
            headers: dict = None) -> dict:
        if not (
                data := self.send_request(
                    api,
                    params=params,
                    headers=headers,
                )):
            print("获取直播数据失败")
            return {}
        return data or {}
